<template>
  <div class="system-menu">
    <TitleContainer spot="菜单详情" />
    <div class="menu-render" v-loading="listLoading">
      <el-tree
        :data="data"
        node-key="id"
        default-expand-all
        :expand-on-click-node="false"
        @node-drag-start="handleDragStart"
        @node-drag-enter="handleDragEnter"
        @node-drag-leave="handleDragLeave"
        @node-drag-over="handleDragOver"
        @node-drag-end="handleDragEnd"
        @node-drop="handleDrop"
        :allow-drop="allowDrop"
        draggable
      >
        <span class="custom-tree-node" slot-scope="{ node, data }">
          <span
            class="default-menu-item"
            :class="
              data.id === 1
                ? 'system-color'
                : data.parent_id === 1
                ? 'child-system'
                : data.children && data.children.length > 0
                ? 'has-child-menu'
                : 'default'
            "
          >
            <svg-icon
              :name="data.icon ? data.icon : 'component'"
              style="margin: 0 5px"
            />
            {{ data.name }}
            <span class="menu-item-route">{{
              data.route ? '(路径：' + data.route + ')' : ''
            }}</span>
          </span>
          <span class="menu-item-option">
            <el-tooltip
              class="item"
              effect="dark"
              content="编辑"
              placement="bottom"
            >
              <el-button
                type="info"
                size="mini"
                icon="el-icon-edit"
                v-if="data.id !== 1"
                circle
                @click="handleUpdate(data)"
              >
              </el-button>
            </el-tooltip>
            <el-tooltip
              class="item"
              effect="dark"
              content="添加子菜单栏"
              placement="bottom"
            >
              <el-button
                type="info"
                size="mini"
                icon="el-icon-plus"
                circle
                @click="handleCreate(data.id)"
              >
              </el-button>
            </el-tooltip>
            <el-tooltip
              class="item"
              effect="dark"
              content="删除"
              placement="bottom"
            >
              <el-button
                type="info"
                size="mini"
                icon="el-icon-delete"
                v-if="data.id !== 1"
                circle
                @click="handleDelete(data)"
              >
              </el-button>
            </el-tooltip>
            <el-tooltip
              class="item"
              effect="dark"
              content="上移顺序"
              placement="bottom"
            >
              <el-button
                type="info"
                size="mini"
                icon="el-icon-arrow-up"
                v-if="data.id !== 1"
                circle
                @click="handleMove(data, 'up')"
              >
              </el-button>
            </el-tooltip>
            <el-tooltip
              class="item"
              effect="dark"
              content="下移顺序"
              placement="bottom"
            >
              <el-button
                type="info"
                size="mini"
                icon="el-icon-arrow-down"
                v-if="data.id !== 1"
                circle
                @click="handleMove(data, 'down')"
              >
              </el-button>
            </el-tooltip>
          </span>
        </span>
      </el-tree>
    </div>
    <el-dialog
      :modal-append-to-body="false"
      :title="textMap[dialogStatus]"
      :visible.sync="dialogFormVisible"
      :close-on-click-modal="false"
      width="600px"
    >
      <el-form
        ref="dataForm"
        :rules="rules"
        :model.sync="tempMenuItem"
        label-position="right"
        label-width="100px"
        style="width: 400px; margin-left:50px;"
      >
        <el-form-item
          :label="
            parseInt(this.tempMenuItem.parent_id) === 1 ? '系统名' : '菜单名'
          "
          prop="name"
        >
          <el-input
            v-model="tempMenuItem.name"
            :placeholder="
              parseInt(this.tempMenuItem.parent_id) === 1 ? '系统名' : '菜单名'
            "
          />
        </el-form-item>
        <el-form-item label="图标" prop="icon">
          <el-popover placement="bottom" width="800" trigger="click">
            <div>
              <div
                v-for="item of svgIcons"
                :key="item"
                @click="handleSelectIcon(item)"
              >
                <el-tooltip placement="top">
                  <div slot="content">
                    {{ item }}
                  </div>
                  <div class="icon-item">
                    <svg-icon :name="item" class="disabled" />
                  </div>
                </el-tooltip>
              </div>
            </div>
            <el-button type="text" slot="reference">
              <el-tooltip
                class="item"
                effect="dark"
                content="请选择图标"
                placement="bottom"
              >
                <svg-icon :name="tempMenuItem.icon" width="20" height="20" />
              </el-tooltip>
            </el-button>
          </el-popover>
        </el-form-item>
        <el-form-item label="路径" prop="route">
          <el-input v-model="tempMenuItem.route" placeholder="请填写路径名" />
        </el-form-item>
        <el-form-item label="编码" prop="code">
          <el-input v-model="tempMenuItem.code" placeholder="编码" />
        </el-form-item>
        <el-form-item label="其他数据" prop="data">
          <el-input v-model="tempMenuItem.data" placeholder="其他数据" />
        </el-form-item>
        <el-form-item label="支持报表" prop="extra">
          <el-checkbox
            v-model="tempMenuItem.extra.support_report"
            :disabled="tempMenuItem.route ? true : false"
          >
            勾选后可在该菜单下创建自定义报表
          </el-checkbox>
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input v-model="tempMenuItem.remark" placeholder="备注" />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible = false">
          {{ '取消' }}
        </el-button>
        <el-button
          type="primary"
          @click="dialogStatus === 'create' ? createData() : updateData()"
        >
          确认
        </el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script lang="ts">
// 具体用法查看官方API:https://github.com/kaorun343/vue-property-decorator
import { Component, Vue, Watch, Prop } from 'vue-property-decorator'
import {
  getMenu,
  menuCreate,
  menuUpdate,
  menuDelete,
  menuMove
} from '@/api/system/menu'
import TitleContainer from '@/components/title/TitleContainer.vue'
import { Form } from 'element-ui'
import { cloneDeep } from 'lodash'
import { Message, MessageBox } from 'element-ui'
const req = require.context('../../icons/svg', false, /\.svg$/)
const re = /\.\/(.*)\.svg/
const requireAll = (requireContext: any) => requireContext.keys()

const svgIcons = requireAll(req).map((str: string) => {
  return str.match(re)![1]
})
interface IData {
  id?: number | string
  name: string
  icon: string
  route: string
  parent_id: string
  data: string
  code: string
  remark: string
  extra: object
}
const defaultData: IData = {
  name: '',
  icon: 'component',
  route: '',
  parent_id: '',
  data: '',
  code: '',
  remark: '',
  extra: {
    support_report: false
  }
}
let id = 1000
@Component({
  name: 'system-menu',
  components: {
    //引用的组件在这里声明
    TitleContainer
  }
})
export default class extends Vue {
  @Prop({ default: '' }) private propExp1!: string
  private svgIcons = svgIcons
  private tempMenuItem = cloneDeep(defaultData)
  // @Prop({ required: true }) private propExp2?: boolean
  private data: any = []
  private listLoading: boolean = false
  // 弹窗配置
  private dialogStatus = ''
  private dialogFormVisible = false
  private textMap = {
    update: '编辑',
    create: '新增'
  }
  get rules() {
    return {
      name: [
        {
          required: true,
          message:
            parseInt(this.tempMenuItem.parent_id) === 1
              ? '请填写系统名'
              : '请填写菜单名',
          trigger: 'blur'
        }
      ]
    }
  }
  get computedExp() {
    //computed 属性
    return true
  }
  created() {
    // 最早可以调用vue组件method的钩子
  }
  mounted() {
    //mounted 钩子
    this.getList()
  }
  private methodExp() {
    // method创建地方
  }
  private async getList() {
    this.listLoading = true
    const { data } = await getMenu()
    let temMenuTree: any = []
    temMenuTree.push(data.root)
    this.data = temMenuTree
    this.listLoading = false
  }
  private append(data: any) {
    const newChild = { id: id++, label: 'testtest', children: [] }
    if (!data.children) {
      this.$set(data, 'children', [])
    }
    data.children.push(newChild)
  }

  private remove(node: any, data: any) {
    const parent = node.parent
    const children = parent.data.children || parent.data
    const index = children.findIndex((d: any) => d.id === data.id)
    children.splice(index, 1)
  }
  // 新增
  private handleCreate(parent_id: any) {
    this.resetData()
    this.tempMenuItem.parent_id = parent_id
    this.dialogStatus = 'create'
    this.dialogFormVisible = true
    this.$nextTick(() => {
      ;(this.$refs['dataForm'] as Form).clearValidate()
    })
  }
  private resetData() {
    this.tempMenuItem = cloneDeep(defaultData)
  }
  // 新增
  private createData() {
    ;(this.$refs['dataForm'] as Form).validate(async valid => {
      if (valid) {
        let tempPostData = {
          name: this.tempMenuItem.name,
          icon: this.tempMenuItem.icon,
          route: this.tempMenuItem.route,
          parent_id: this.tempMenuItem.parent_id,
          data: this.tempMenuItem.data,
          remark: this.tempMenuItem.remark,
          code: this.tempMenuItem.code,
          extra: this.tempMenuItem.extra
        }
        const { data } = await menuCreate(tempPostData)
        this.dialogFormVisible = false
        this.$notify({
          title: '成功',
          message: '创建成功',
          type: 'success',
          duration: 2000
        })
        setTimeout(() => {
          location.reload()
        }, 0)
      }
    })
  }
  // 打开弹窗编辑
  private async handleUpdate(row: any) {
    this.tempMenuItem = cloneDeep(row)
    this.tempMenuItem.icon = this.tempMenuItem.icon
      ? this.tempMenuItem.icon
      : 'component'
    this.dialogStatus = 'update'
    this.dialogFormVisible = true
    this.$nextTick(() => {
      ;(this.$refs['dataForm'] as Form).clearValidate()
    })
  }
  // 更新
  private updateData() {
    ;(this.$refs['dataForm'] as Form).validate(async valid => {
      if (valid) {
        let tempPostData = {
          id: parseInt(this.tempMenuItem.id as string),
          name: this.tempMenuItem.name,
          icon: this.tempMenuItem.icon,
          route: this.tempMenuItem.route,
          parent_id: this.tempMenuItem.parent_id,
          data: this.tempMenuItem.data,
          remark: this.tempMenuItem.remark,
          code: this.tempMenuItem.code,
          extra: this.tempMenuItem.extra
        }
        const { data } = await menuUpdate(tempPostData)
        this.dialogFormVisible = false
        this.$notify({
          title: '成功',
          message: '更新成功',
          type: 'success',
          duration: 2000
        })
        setTimeout(() => {
          location.reload()
        }, 0)
      }
    })
  }

  // 打开弹窗编辑
  private async handleDelete(row: any) {
    this.tempMenuItem = cloneDeep(row)
    MessageBox.confirm(`确定删除${row.name}菜单？`, '确定', {
      confirmButtonText: '删除',
      cancelButtonText: '取消',
      type: 'warning'
    }).then(async () => {
      const { data } = await menuDelete({ id: this.tempMenuItem.id })
      this.dialogFormVisible = false
      this.$notify({
        title: '成功',
        message: '删除成功',
        type: 'success',
        duration: 2000
      })
      setTimeout(() => {
        location.reload()
      }, 0)
    })
  }
  private async handleMove(row: any, direction: string) {
    this.tempMenuItem = cloneDeep(row)
    const { data } = await menuMove({
      id: this.tempMenuItem.id,
      direction: direction
    })
    this.$notify({
      title: '成功',
      message: direction === 'up' ? '上移成功' : '下移成功',
      type: 'success',
      duration: 2000
    })
    this.getList()
  }
  private handleSelectIcon(item: any) {
    this.tempMenuItem.icon = item
  }

  private handleDragStart(node: any, ev: any) {
    // 开始拖动
  }
  private handleDragEnter(draggingNode: any, dropNode: any, ev: any) {
    console.log(dropNode.data.id)
    console.log(dropNode.data.name)
    // 进入某个节点
  }
  private handleDragLeave(draggingNode: any, dropNode: any, ev: any) {
    // 离开某个节点
  }
  private handleDragOver(draggingNode: any, dropNode: any, ev: any) {
    // 经过某个节点
  }
  private handleDragEnd(
    draggingNode: any,
    dropNode: any,
    dropType: any,
    ev: any
  ) {
    // 目标位置
  }
  private async handleDrop(
    draggingNode: any,
    dropNode: any,
    dropType: any,
    ev: any
  ) {
    let tempPostData = cloneDeep(draggingNode.data)
    tempPostData.parent_id = dropNode.data.id
    const { data } = await menuUpdate(tempPostData)
    this.$notify({
      title: '成功',
      message: '更新成功',
      type: 'success',
      duration: 2000
    })
    console.log(this.data)
    /* setTimeout(() => {
      location.reload()
    }, 0) */
  }
  // 不允许同级别改变顺序拖动
  private allowDrop(draggingNode: any, dropNode: any, type: any) {
    if (type === 'inner') {
      /* if (dropNode.data.parent_id === draggingNode.data.parent_id) {
        return false
      } else {
        return true
      } */
      return true
    } else {
      return false
    }
  }
}
</script>
<style lang="scss">
.icon-item {
  margin: 10px;
  height: 30px;
  text-align: center;
  width: 50px;
  float: left;
  font-size: 20px;
  color: #24292e;
  cursor: pointer;
}
</style>
<style lang="scss" scoped>
.system-menu {
  padding: 20px;
  .menu-button-group {
    margin: 20px 0 5px;
  }
  .menu-render {
    margin-top: 10px;
    min-height: 20px;
    width: 870px;
    padding: 24px;
    border: 1px solid #ebebeb;
    border-radius: 3px;
    transition: 0.2s;
    &:hover {
      box-shadow: 0 0 8px 0 rgba(232, 237, 250, 0.6),
        0 2px 4px 0 rgba(232, 237, 250, 0.5);
    }

    .custom-tree-node {
      flex: 1;
      display: flex;
      align-items: center;
      justify-content: space-between;
      font-size: 14px;
      padding-right: 8px;
      .el-button--mini.is-circle {
        padding: 3px;
      }
      .menu-item-option {
        visibility: hidden;
      }
      .menu-item-route {
        margin-left: 10px;
        visibility: hidden;
      }
      &:hover {
        .menu-item-option {
          visibility: visible;
        }
        .menu-item-route {
          visibility: visible;
          font-size: 14px;
          color: $darkGray;
        }
      }
      .system-color {
        font-size: 18px;
        font-weight: 800;
      }
      .child-system {
        font-size: 16px;
        color: $systemYellow;
      }
      .has-child-menu {
        font-size: 14px;
        color: $clickableBlue;
      }
    }
  }
}
</style>
